home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d3 / Telnet2.6.1d3.src.sit.hqx / Telnet 2.6.1d3 source / source / main / DlogUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-18  |  18.3 KB  |  688 lines

  1. /*
  2. *    DlogUtils.c
  3. *    Very Useful Dialog Utilities Apple SHOULD have provided in the toolbox...
  4. *
  5. *****************************************************************
  6. *    NCSA Telnet for the Macintosh                                *
  7. *                                                                *
  8. *    National Center for Supercomputing Applications                *
  9. *    Software Development Group                                    *
  10. *    152 Computing Applications Building                            *
  11. *    605 E. Springfield Ave.                                        *
  12. *    Champaign, IL  61820                                        *
  13. *                                                                *
  14. *    Copyright (c) 1986-1992,                                    *
  15. *    Board of Trustees of the University of Illinois                *
  16. *****************************************************************
  17. *  Revisions:
  18. *  8/92        Telnet 2.6:    Initial version.  Jim Browne
  19. */
  20.  
  21. #ifdef MPW
  22. #pragma segment 7
  23. #endif
  24.  
  25. #include "TelnetHeader.h"
  26. #include "DlogUtils.proto.h"
  27. #include "netevent.proto.h"
  28. #include "newresrc.h"
  29.  
  30. #include "Popup.h"
  31. #include "popup.proto.h"
  32.  
  33. pascal short modalProc(DialogPtr dptr, EventRecord *evt, short *item);
  34. PROTO_UPP(modalProc, ModalFilter);
  35. pascal short FileHook(short item, DialogPtr theDialog);
  36. PROTO_UPP(FileHook, DlgHook);
  37. pascal Boolean    FolderFilter(FileParam *pbp);
  38. PROTO_UPP(FolderFilter, FileFilter);
  39.  
  40. void GetTEText( DialogPtr dptr, short item, Str255 str)
  41. {
  42.     short type;
  43.     Handle itemh;
  44.     Rect theRect;
  45.  
  46.     GetDItem(dptr, item, &type, &itemh, &theRect);
  47.     GetIText(itemh, str);
  48. }
  49.  
  50. void SetTEText( DialogPtr dptr, short item, Str255 str)
  51. {
  52.     short type;
  53.     Handle itemh;
  54.     Rect theRect;
  55.  
  56.     GetDItem(dptr, item, &type, &itemh, &theRect);
  57.     SetIText(itemh, str);
  58. }
  59.  
  60. void Hilite( DialogPtr dptr, short item, short value)
  61. {
  62.     short Type;
  63.     Handle Itemh;
  64.     Rect Box;
  65.  
  66.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  67.     HiliteControl((ControlHandle)Itemh, value);
  68. }
  69.  
  70. void FlipCheckBox( DialogPtr dptr, short item)
  71. {
  72.     short type;
  73.     Handle itemHdl;
  74.     Rect box;
  75.  
  76.     GetDItem(dptr, item, &type, &itemHdl, &box);
  77.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  78. }
  79.  
  80. void FlipRadioButton( DialogPtr dptr, short item)
  81. {
  82.     short type;
  83.     Handle itemHdl;
  84.     Rect box;
  85.  
  86.     GetDItem(dptr, item, &type, &itemHdl, &box);
  87.     SetCtlValue((ControlHandle)itemHdl, (GetCtlValue((ControlHandle)itemHdl) == 0) ? 1 : 0);
  88. }
  89.  
  90. void SetCntrl( DialogPtr dptr, short item, short value)
  91. {
  92.     short Type;
  93.     Handle Itemh;
  94.     Rect Box;
  95.  
  96.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  97.     SetCtlValue((ControlHandle)Itemh, value);
  98. }
  99.  
  100. short GetCntlVal( DialogPtr dptr, short item)
  101. {
  102.     short Type;
  103.     Handle Itemh;
  104.     Rect Box;
  105.  
  106.     GetDItem(dptr, item, &Type, &Itemh, &Box);
  107.     return GetCtlValue((ControlHandle)Itemh);
  108. }
  109.  
  110. #ifndef NO_UNIVERSAL
  111. void UItemAssign( DialogPtr dptr, short item, UserItemUPP proc)
  112. #else
  113. void UItemAssign( DialogPtr dptr, short item, ProcPtr proc)
  114. #endif
  115. /* sets the handler for a user item to the specified procedure. */
  116. {
  117.     Rect ibox;
  118.     char **ihndl;
  119.     short typ;
  120.  
  121.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  122.     SetDItem( dptr, item,  typ, (Handle) proc, &ibox);
  123. }
  124.  
  125. SIMPLE_UPP(OutlineItem, UserItem);
  126. pascal void OutlineItem( DialogPtr dptr, short itm)
  127. {
  128.     Rect ibox;
  129.     char **ihndl;
  130.     short typ;
  131.     short item=itm;
  132.     
  133.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  134.     PenSize( 3,3);
  135.     InsetRect( &ibox, -4,-4);
  136.     FrameRoundRect( &ibox, 16,16);
  137. }
  138.  
  139. SIMPLE_UPP(VersionNumber, UserItem);
  140. pascal void VersionNumber( DialogPtr dptr, short itm)
  141. {
  142.     Rect ibox;
  143.     char **ihndl;
  144.     short typ;
  145.     short item=itm;
  146.     VersRecHndl version;
  147.     Str63 versionString;
  148.  
  149.     if ((version = (VersRecHndl) GetResource('vers',1)) != nil)
  150.     {
  151.         BlockMove((*version)->shortVersion+*(*version)->shortVersion+1, versionString, *((*version)->shortVersion+*(*version)->shortVersion+1)+1);
  152.         ReleaseResource((Handle)version);
  153.     }
  154.     else
  155.         *versionString = 0;
  156.  
  157.     GetDItem( dptr, item, &typ, &ihndl, &ibox);
  158.     TextFont( 3);
  159.     TextSize( 9);
  160.     MoveTo( ibox.left+((ibox.right-ibox.left)/2)-(StringWidth(versionString)/2), ibox.bottom-2);
  161.     DrawString(versionString);
  162. }
  163.  
  164. SIMPLE_UPP(modalProc, ModalFilter);
  165. pascal short modalProc( DialogPtr dptr, EventRecord *evt, short *item)
  166. {
  167.     UNUSED_ARG(dptr)
  168.     short keyCode, key;
  169.  
  170.     if (evt->what == keyDown) {
  171.         key = evt->message & charCodeMask;
  172.         keyCode = (evt->message >>8) & 0xff ;
  173.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  174.             *item = DLOGOk;
  175.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  176.             }
  177.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  178.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  179.             *item = DLOGCancel;
  180.             return(-1);                /* BYU LSC - pascal doesn't like "1" as true */
  181.             }
  182.         }
  183.     Stask();
  184.     return(FALSE);
  185. }
  186.  
  187. void FlashButton (DialogPtr theDialog, short item)
  188. {
  189.     short itemType;
  190.     ControlHandle theItem;
  191.     Rect itemRect;
  192.     long myticks;
  193.     
  194.     if (item > 0) {
  195.         GetDItem(theDialog,item,&itemType,(Handle *)&theItem,&itemRect);
  196.         HiliteControl(theItem,1);
  197.         Delay(8,&myticks);
  198.         HiliteControl(theItem,0);
  199.     }
  200. }
  201.  
  202. SIMPLE_UPP(DLOGwOK, ModalFilter);
  203. pascal short DLOGwOK( DialogPtr dptr, EventRecord *evt, short *item)
  204. {
  205.     return(MyDLOGfilter(dptr, evt, item, true, false, false));
  206. }
  207.  
  208. SIMPLE_UPP(DLOGwOK_Cancel, ModalFilter);
  209. pascal short DLOGwOK_Cancel( DialogPtr dptr, EventRecord *evt, short *item)
  210. {
  211.     return(MyDLOGfilter(dptr, evt, item, true, true, false));
  212. }
  213.  
  214. SIMPLE_UPP(DLOGwOK_Cancel_Popup, ModalFilter);
  215. pascal short DLOGwOK_Cancel_Popup( DialogPtr dptr, EventRecord *evt, short *item)
  216. {
  217.     return(MyDLOGfilter(dptr, evt, item, true, true, true));
  218. }
  219.  
  220. //    Our standard modal dialog box filter.
  221. SIMPLE_UPP(MyDLOGfilter, ModalFilter);
  222. pascal short MyDLOGfilter( DialogPtr dptr, EventRecord *evt, short *item, 
  223.                             Boolean hasOK, Boolean hasCancel, Boolean hasPopup)
  224. {
  225.     short keyCode, key, iType;
  226.     Handle iHndl;
  227.     Rect iRect;
  228.  
  229.     SetPort(dptr);
  230.     if (evt->what == keyDown) {
  231.         key = evt->message & charCodeMask;
  232.         keyCode = (evt->message >>8) & 0xff ;
  233.         if (((key == 0x0d) || (key == 0x03)) && hasOK) { // 0x0d == return, 0x03 == enter
  234.             *item = DLOGOk;                // ok
  235.             FlashButton(dptr, DLOGOk);
  236.             return(-1);
  237.             }
  238.         if ((((key == '.') && (evt->modifiers & cmdKey)) ||
  239.             ((key == 0x1b) && (keyCode == 0x35))) && hasCancel) {    // 0x35 == escKey
  240.             *item = DLOGCancel;
  241.             FlashButton(dptr, DLOGCancel);
  242.             return(-1);
  243.             }
  244.         }
  245.     else if ((evt->what == updateEvt) && hasOK) {
  246.         if ((WindowPtr)evt->message == dptr) {
  247.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  248.             PenSize(3,3);
  249.             InsetRect(&iRect,-4,-4);
  250.             FrameRoundRect(&iRect,16,16);
  251.             }
  252.     }
  253.     
  254.     if ((evt->what == mouseDown) && hasPopup)
  255.         return(PopupMousedown(dptr, evt, item));
  256.  
  257.     Stask();
  258.     return(FALSE);
  259. }
  260.  
  261. #if 0
  262. //    Our standard modal dialog box filter with code to handle popup user items.
  263. pascal short MyDLOGfilterWPopupFilter( DialogPtr dptr, EventRecord *evt, short *item)
  264. {
  265.     short keyCode, key, iType;
  266.     Handle iHndl;
  267.     Rect iRect;
  268.  
  269.     SetPort(dptr);
  270.     if (evt->what == keyDown) {
  271.         key = evt->message & charCodeMask;
  272.         keyCode = (evt->message >>8) & 0xff ;
  273.         if ((key == 0x0d) || (key == 0x03)) { // 0x0d == return, 0x03 == enter
  274.             *item = DLOGOk;                // ok
  275.             FlashButton(dptr, DLOGOk);
  276.             return(-1);
  277.             }
  278.         if (((key == '.') && (evt->modifiers & cmdKey)) ||
  279.             ((key == 0x1b) && (keyCode == 0x35)) ) {    // 0x35 == escKey
  280.             *item = DLOGCancel;
  281.             FlashButton(dptr, DLOGCancel);
  282.             return(-1);
  283.             }
  284.         }
  285.     else if (evt->what == updateEvt) {
  286.         if ((WindowPtr)evt->message == dptr) {
  287.             GetDItem(dptr,DLOGOk,&iType,&iHndl,&iRect);    // ok
  288.             PenSize(3,3);
  289.             InsetRect(&iRect,-4,-4);
  290.             FrameRoundRect(&iRect,16,16);
  291.             }
  292.     }
  293.     
  294.     if (evt->what == mouseDown) return(PopupMousedown(dptr, evt, item));
  295.     Stask();
  296.     return(FALSE);
  297. }
  298. #endif
  299.  
  300. #ifdef    NO_UNIVERSAL
  301. #define LMSetSFSaveDisk(SFSaveDiskValue) ((* (short *) 0x0214) = (SFSaveDiskValue))
  302. #define LMGetSFSaveDisk() (* (short *) 0x0214)
  303. #define LMGetCurDirStore() (* (long *) 0x0398)
  304. #define LMSetCurDirStore(CurDirStoreValue) ((* (long *) 0x0398) = (CurDirStoreValue))
  305. #endif
  306.  
  307. void    SelectDirectory(short *VRefNum, long *DirID)
  308. {
  309.     Point        where;
  310.     SFReply        sfr;
  311.     
  312.     LMSetSFSaveDisk( - (*VRefNum));
  313.     LMSetCurDirStore(*DirID);
  314.     
  315.     StandardFileCenter(&where, WDSET_DLOG);
  316.     
  317.     TelInfo->setdir = 0;                    /* clear dir found flag */
  318.     
  319.     SFPGetFile( where, NULL, FolderFilterUPP, -1, NULL,    /* BYU LSC */
  320.         FileHookUPP, &sfr, WDSET_DLOG,
  321.         modalProcUPP); 
  322.  
  323.     if (TelInfo->setdir)    {                /* we got a dir */
  324.         *VRefNum = - LMGetSFSaveDisk();
  325.         *DirID = LMGetCurDirStore();
  326.         }
  327. //    else {
  328. //        if(!sfr.good) return;    /* real cancel button got hit */
  329. //        GetWDInfo(sfr.vRefNum, VRefNum, DirID, &junk);
  330. //    }
  331.     
  332. }
  333.  
  334. SIMPLE_UPP(FileHook, DlgHook);
  335. pascal short    FileHook( short item, DialogPtr theDialog)
  336. {
  337. #ifdef    MPW
  338. #pragma unused(theDialog)
  339. #endif
  340.     if(item == 11) {                    /* Set Directory Button */
  341.             TelInfo->setdir = 1;
  342.             
  343.             return(3);        /* pretend we hit cancel, but we didn't */
  344.         }
  345.     else if (item == 12)
  346.         item = 9;            /* these don't count, map to disabled item */
  347.  
  348.     return(item);
  349. }
  350.  
  351. SIMPLE_UPP(FolderFilter, FileFilter);
  352. pascal Boolean    FolderFilter(FileParam *pbp)
  353. {
  354.     if (pbp->ioFlAttrib & 0x0010) return(FALSE);
  355.     else return(-1);
  356. }
  357.  
  358. OSErr SetIndString(StringPtr theStr,short resID,short strIndex)
  359. {
  360.    Handle theRes;               /* handle pointing to STR# resource */
  361.    short numStrings;            /* number of strings in STR# */
  362.    short ourString;             /* counter to index up to strIndex */
  363.    char *resStr;                /* string pointer to STR# string to replace */
  364.    long oldSize;                /* size of STR# resource before call */
  365.    long newSize;                /* size of STR# resource after call */
  366.    unsigned long offset;        /* resource offset to str to replace*/
  367.  
  368.    /* make sure index is in bounds */
  369.  
  370.    if (resID < 1)
  371.    return -1;
  372.  
  373.    /* make sure resource exists */
  374.  
  375.    theRes = GetResource('STR#',resID);
  376.    if (ResError()!=noErr)
  377.    return ResError();
  378.    if (!theRes || !(*theRes))
  379.    return resNotFound;
  380.  
  381.    HLock(theRes);
  382.    HNoPurge(theRes);
  383.  
  384.    /* get # of strings in STR# */
  385.  
  386.    BlockMove(*theRes,&numStrings,sizeof(short));
  387.    if (strIndex > numStrings)
  388.    return resNotFound;
  389.  
  390.    /* get a pointer to the string to replace */
  391.  
  392.    offset = sizeof(short);
  393.    resStr = (char *) *theRes + sizeof(short);
  394.    for (ourString=1; ourString<strIndex; ourString++) {
  395.    offset += 1+resStr[0];
  396.    resStr += 1+resStr[0];
  397.    }
  398.  
  399.    /* grow/shrink resource handle to make room for new string */
  400.  
  401.    oldSize = GetHandleSize(theRes);
  402.    newSize = oldSize - resStr[0] + theStr[0];
  403.    HUnlock(theRes);
  404.    SetHandleSize(theRes,newSize);
  405.    if (MemError()!=noErr) {
  406.    ReleaseResource(theRes);
  407.    return -1;
  408.    }
  409.    HLock(theRes);
  410.    resStr = *theRes + offset;
  411.  
  412.    /* move old data forward/backward to make room */
  413.  
  414.    BlockMove(resStr+resStr[0]+1, resStr+theStr[0]+1, oldSize-offset-resStr[0]-1);
  415.  
  416.    /* move new data in */
  417.  
  418.    BlockMove(theStr,resStr,theStr[0]+1);
  419.  
  420.    /* write resource out */
  421.  
  422.    ChangedResource(theRes);
  423.    WriteResource(theRes);
  424.    HPurge(theRes);
  425.    ReleaseResource(theRes);
  426.  
  427.    return ResError();
  428. }
  429.  
  430. /* A very special thanks to Steve Dorner (sdorner@qualcomm.com) for the following code! */
  431.  
  432. /************************************************************************
  433.  * GetNewMyDialog - get a new dialog, with a bit extra
  434.  ************************************************************************/
  435. WindowPtr GetNewMyDialog(short template,Ptr wStorage,WindowPtr behind,
  436.     void (*centerFunction)(short))
  437. {
  438.     WindowPtr win;
  439.     
  440.     if (wStorage == nil)
  441.     {
  442.         if ((wStorage=NewPtr(sizeof(DialogRecord)))==nil)
  443.             return (nil);
  444.     }
  445.     WriteZero(wStorage, sizeof(WindowRecord));
  446.     
  447.     (*centerFunction)(template);
  448.     win = GetNewDialog(template, wStorage, behind);
  449.     if (win==nil) return(nil);
  450.     SetPort(win);
  451. /*    win->contR = ((GrafPtr)win)->portRect; */
  452. /*    win->qWindow.refCon = CREATOR; */
  453.     return(win);
  454. }
  455.  
  456. /* Do a GetNewMyDialog, but make the text small... */
  457. WindowPtr GetNewMySmallDialog(short template,Ptr wStorage,WindowPtr behind,
  458.     void (*centerFunction)(short))
  459. {
  460.     short size;
  461.     DialogPtr dlogptr;
  462.     
  463.     size = 9;
  464.     SetDAFont(applFont);
  465.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  466.     SetDAFont(systemFont);
  467.     if (dlogptr==nil)
  468.         return 0;
  469.     SetPort(dlogptr);
  470.     TextSize(size);
  471.     TextFont(applFont);
  472.     {
  473.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  474.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  475.         (*teh)->txSize = size;
  476.         (*teh)->lineHeight = GetLeading(applFont,size);
  477.         (*teh)->fontAscent = GetAscent(applFont,size);
  478.     }            
  479.  
  480.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  481.         and then do a ShowWindow.  This keeps the Control Manager from every using Chicago
  482.         on our turf. -- JMB */
  483.         
  484.     if (! ((((DialogPeek) dlogptr)->window).visible)) ShowWindow(dlogptr);
  485.     
  486.     return(dlogptr);
  487. }
  488.  
  489. /* Do a GetNewMySmallDialog, but read the item titles from a STR#... */
  490. WindowPtr GetNewMySmallStrangeDialog(short template,Ptr wStorage,WindowPtr behind,
  491.     void (*centerFunction)(short))
  492. {
  493.     short         size, index, limit, itemType;
  494.     DialogPtr     dlogptr;
  495.     Handle        resource;
  496.     ControlHandle    itemHandle;
  497.     Rect        scratchRect;
  498.     Str255        scratchPstring;
  499.     
  500.     size = 9;
  501.     SetDAFont(applFont);
  502.     dlogptr = GetNewMyDialog(template,wStorage,behind,centerFunction);
  503.     SetDAFont(systemFont);
  504.     if (dlogptr==nil)
  505.         return 0;
  506.     SetPort(dlogptr);
  507.     TextSize(size);
  508.     TextFont(applFont);
  509.     {
  510.         TEHandle teh = ((DialogPeek)dlogptr)->textH;
  511.         ControlHandle cntl = ((WindowPeek)dlogptr)->controlList;
  512.         (*teh)->txSize = size;
  513.         (*teh)->lineHeight = GetLeading(applFont,size);
  514.         (*teh)->fontAscent = GetAscent(applFont,size);
  515.     }            
  516.  
  517.     /*     For those dialogs with non-system font buttons, make them inititally invisible
  518.         and then do a ShowWindow.  This keeps the Control Manager from ever using Chicago
  519.         on our turf. -- JMB */
  520.     
  521.     if ((resource = GetResource('STR#', template)) != NULL) {
  522.         limit = *(short *)(*resource);
  523.         ReleaseResource(resource);
  524.         
  525.         for(index = 1; index <= limit; index++) {
  526.             GetDItem(dlogptr, index, &itemType, (Handle *)&itemHandle, &scratchRect);
  527.             if ((itemType == 7) && ((**itemHandle).contrlRfCon == 1991)) {
  528.                 GetIndString(scratchPstring, template, index);
  529.                 SetCTitle(itemHandle, scratchPstring);
  530.                 }
  531.             }
  532.         }
  533.                 
  534.     return(dlogptr);
  535. }
  536.  
  537. /**********************************************************************
  538.  * write zeroes over an area of memory
  539.  **********************************************************************/
  540. void WriteZero(Ptr pointer,long size)
  541. {
  542.     while (size--) *pointer++ = 0;
  543. }
  544.  
  545. /**********************************************************************
  546.  * figure out the appropriate leading for a font
  547.  **********************************************************************/
  548. short GetLeading(short fontID,short fontSize)
  549. {
  550.     FMInput fInInfo;
  551.     FMOutput *fOutInfo;
  552.     
  553.     /* set up the font input struct */
  554.     fInInfo.family = fontID;
  555.     fInInfo.size = fontSize;
  556.     fInInfo.face = 0;
  557.     fInInfo.needBits = FALSE;
  558.     fInInfo.device = 0;
  559.     fInInfo.numer.h = fInInfo.numer.v = 1;
  560.     fInInfo.denom.h = fInInfo.denom.v = 1;
  561.     
  562.     /* get the actual info */
  563.     fOutInfo = FMSwapFont(&fInInfo);
  564.     
  565.     return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
  566. }
  567.  
  568. /**********************************************************************
  569.  * find ascent font
  570.  **********************************************************************/
  571. short GetAscent(short fontID,short fontSize)
  572. {
  573.     FMInput fInInfo;
  574.     FMOutput *fOutInfo;
  575.     
  576.     /*    set up the font input struct */
  577.     fInInfo.family = fontID;
  578.     fInInfo.size = fontSize;
  579.     fInInfo.face = 0;
  580.     fInInfo.needBits = FALSE;
  581.     fInInfo.device = 0;
  582.     fInInfo.numer.h = fInInfo.numer.v = 1;
  583.     fInInfo.denom.h = fInInfo.denom.v = 1;
  584.     
  585.     /*    get the actual info */
  586.     fOutInfo = FMSwapFont(&fInInfo);
  587.     
  588.     return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
  589. }
  590.  
  591. /************************************************************************
  592.  * CenterRectIn - center one rect in another
  593.  ************************************************************************/
  594. void CenterRectIn(Rect *inner,Rect *outer)
  595. {
  596.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  597.                                      (outer->top+outer->bottom-inner->top-inner->bottom)/2);                                                                    
  598. }
  599.  
  600. /************************************************************************
  601.  * TopCenterRectIn - center one rect in (the bottom of) another
  602.  ************************************************************************/
  603. void TopCenterRectIn(Rect *inner,Rect *outer)
  604. {
  605.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  606.                                      outer->top-inner->top);                                                                    
  607. }
  608.  
  609. /************************************************************************
  610.  * BottomCenterRectIn - center one rect in (the bottom of) another
  611.  ************************************************************************/
  612. void BottomCenterRectIn(Rect *inner,Rect *outer)
  613. {
  614.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  615.                                      outer->bottom-inner->bottom);                                                                    
  616. }
  617.  
  618. /************************************************************************
  619.  * ThirdCenterRectIn - center one rect in (the top 1/3 of) another
  620.  ************************************************************************/
  621. void ThirdCenterRectIn(Rect *inner,Rect *outer)
  622. {
  623.     OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2, 
  624.                                      outer->top-inner->top +
  625.                                      (outer->bottom-outer->top-inner->bottom+inner->top)/3);                                                                    
  626. }
  627.  
  628. void ThirdCenterDialog(short template)
  629. {
  630.   DialogTHndl dTempl;
  631.   Rect r = qd.screenBits.bounds;
  632.   r.top += GetMBarHeight();       
  633.   if ((dTempl=(DialogTHndl)GetResource('ALRT',template)) ||
  634.       (dTempl=(DialogTHndl)GetResource('DLOG',template)))
  635.     ThirdCenterRectIn(&(*dTempl)->boundsRect,&r);
  636. }
  637.  
  638. /************************************************************************
  639.  * StandardFileCenter - figure out where a stdfile dialog should go
  640.  ************************************************************************/
  641. void StandardFileCenter(Point *where, short id)
  642. {
  643.     Rect r,in;
  644.     DialogTHndl dTempl;             
  645.     if ((dTempl=(DialogTHndl)GetResource('ALRT',id)) ||
  646.             (dTempl=(DialogTHndl)GetResource('DLOG',id)))
  647.     {
  648.         r = (*dTempl)->boundsRect;
  649.         in = qd.screenBits.bounds;
  650.         in.top += GetMBarHeight();
  651.         ThirdCenterRectIn(&r,&in);
  652.         where->h = r.left;
  653.         where->v = r.top;
  654.     }
  655.     else
  656.     {
  657.         where->h = 100;
  658.         where->v = 100;
  659.     }
  660. }
  661.  
  662. /* Pascal string utilities */
  663.  
  664. /*    pstrcat - add string 'src' to end of string 'dst' */
  665. void pstrcat(StringPtr dst, StringPtr src)
  666. {
  667.     /* copy string in */
  668.     BlockMove(src + 1, dst + *dst + 1, *src);
  669.     /* adjust length byte */
  670.     *dst += *src;
  671. }
  672.  
  673. /*    pstrinsert - insert string 'src' at beginning of string 'dst' */
  674. void pstrinsert(StringPtr dst, StringPtr src)
  675. {
  676.     /* make room for new string */
  677.     BlockMove(dst + 1, dst + *src + 1, *dst);
  678.     /* copy new string in */
  679.     BlockMove(src + 1, dst + 1, *src);
  680.     /* adjust length byte */
  681.     *dst += *src;
  682. }
  683.  
  684. void pstrcpy(StringPtr dst, StringPtr src)
  685. {
  686.     BlockMove(src, dst, *src + 1);
  687. }
  688.